/*******************************************************************************
 * Simple C-K Editor
 * 
 * Copyright (C) 2009 Ingi BROWN - Centre de Gestion Scientifique - Ecole des Mines ParisTech
 * Licensed under the GNU General Public License Version 3.
 * 
 * Simple C-K Editor includes source code and libraries from the JUNG Project (Java Universal Network/Graph Framework) 
 * released under the BSD license. Copyright (c) 2003-2004,  Regents of the University of California and the JUNG Project.
 * 
 * See the License.txt file for more details.
 ******************************************************************************/

package edu.ensmp.ckEditor.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

import org.apache.commons.collections15.Transformer;

import edu.ensmp.ckEditor.ckModel.CKModel.Concept;
import edu.ensmp.ckEditor.util.UiConstants;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.algorithms.layout.StaticLayout;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position;

/**
 * GraphPanel is an extension of a JPanel in which we add the different JUNG
 * components to display our Graph. The added JUNG components are: - A
 * Visualization Viewer with its associated Renderer (defines the rendering
 * parameters) - A Layout Manager (manages the coordinates of the vertices)
 */
@SuppressWarnings("serial")
public class GraphPanel<V, E> extends JPanel {

	/*
	 * Private variables used in this class
	 */
	private JLabel label; // Label at the top of the Panel
	private Graph<V, E> graph; // An instance of our implementation of JUNG
								// Graph.
	final private VisualizationViewer<V, E> visuViewer; // The visualization
														// viewer manages the
														// display of the Graph
	private Layout<V, E> staticLayout;

	/*
	 * The class constructor
	 */
	public GraphPanel() {

		// Instantiate the graph
		graph = new Graph<V, E>();

		// Create a static layout (so that we can decide on the positions of
		// each vertex)
		staticLayout = new StaticLayout<V, E>(graph);

		// Set the initial size of the layout space
		staticLayout.setSize(new Dimension(UiConstants.WINDOW_WIDTH / 2,
				UiConstants.WINDOW_HEIGHT));

		// Create the visualization viewer.
		// The BasicVisualizationServer<V,E> is parameterized by the vertex and
		// edge types.
		visuViewer = new VisualizationViewer<V, E>(staticLayout);
		// Set the viewing area size
		visuViewer.setPreferredSize(new Dimension(UiConstants.WINDOW_WIDTH / 2,
				UiConstants.WINDOW_HEIGHT));

		/*
		 * Set up 3 Transformers for tuning our visualization viewer
		 */
		// A Transformer for wrapping the labels into block texts (Formating is
		// done by HTML)
		Transformer<V, String> stringLabeller = new Transformer<V, String>() {
			public String transform(V concept) {
				String label = concept.toString();
				final String breaker = "<p>";
				final int lineWrap = UiConstants.MAX_CHARACTERS_PER_LINE;

				StringBuilder result = new StringBuilder(label);
				int len = lineWrap;
				while (len < result.length()) {
					int idx = result.lastIndexOf(" ", len);
					if (idx != -1) {
						result.replace(idx, idx + 1, breaker);
						len = idx + breaker.length() + lineWrap;
					} else {
						result.insert(len, breaker);
						len += breaker.length() + lineWrap;
					}
				}
				result.insert(0, "<html>");
				return result.toString();
			}
		};

		// Setup up a new concept to paint transformer in order to paint the
		// vertices.
		Transformer<V, Paint> vertexPaint = new Transformer<V, Paint>() {
			public Paint transform(V c) {
				Color color = UiConstants.BACKGROUND_COLOR;
				if(c.getClass() == Concept.class){
					// Concept concept = (Concept)c;
					// TODO
					
				}
				return color;
			}
		};

		// Setup a concept to shape transformer so that vertex is size of the
		// label.
		Transformer<V, Shape> vertexShape = new Transformer<V, Shape>() {
			public Shape transform(V c) {
				int labelLength = c.toString().length();
				int width;
				int height;

				if (labelLength < UiConstants.MAX_CHARACTERS_PER_LINE) {
					width = labelLength * 6;
					height = 10;
				} else {
					width = UiConstants.MAX_CHARACTERS_PER_LINE * 6;
					height = (int) (labelLength * 16 / UiConstants.MAX_CHARACTERS_PER_LINE);
				}
				Point center = new Point(-width / 2, -height / 2);				
				return new Rectangle(center, new Dimension(width, height));
			}
		};

		// Apply the different rendering modifiers (Basically making everything
		// the same color to "hide" the vertex shape )
		visuViewer.setBackground(UiConstants.BACKGROUND_COLOR); // Set
																// background to
																// white!
		visuViewer.getRenderContext()
				.setVertexFillPaintTransformer(vertexPaint); // Vertex fill with
																// white
		visuViewer.getRenderContext()
				.setVertexDrawPaintTransformer(vertexPaint); // Vertex stroke
																// white
		visuViewer.getRenderContext().setVertexShapeTransformer(vertexShape); // Make
																				// vertex
																				// shape
																				// the
																				// size
																				// of
																				// the
																				// label
		
		// Make the vertex show labels in the visuViewer.
		visuViewer.getRenderContext().setVertexLabelTransformer(stringLabeller);
		// Center Label
		visuViewer.getRenderer().getVertexLabelRenderer().setPosition(
				Position.CNTR);
		

		// Setup the panel layout
		this.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		// Add a label on the top of the Panel
		label = new JLabel("Test");
		label.setForeground(Color.GRAY);
		label.setHorizontalAlignment(SwingConstants.CENTER);
		c.gridy = 0;
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.fill = GridBagConstraints.HORIZONTAL;
		add(label, c);

		// Add the visualization viewer to our Concept Panel
		c.fill = GridBagConstraints.BOTH;
		c.gridy = 1;
		c.weightx = 1;
		c.weighty = 1;
		add(visuViewer, c);
	}

	/*
	 * Getters and Setters
	 */
	/**
	 * @return the conceptGraph
	 */
	public Graph<V, E> getGraph() {
		return graph;
	}

	/**
	 * @return the graphLayout
	 */
	public Layout<V, E> getGraphLayout() {
		return staticLayout;
	}

	/**
	 * @param graph
	 *            the graph to set
	 */
	public void setGraph(Graph<V, E> graph) {
		this.graph = graph;
	}

	/**
	 * @return the visuViewer
	 */
	public VisualizationViewer<V, E> getVisuViewer() {
		return visuViewer;
	}

	/**
	 * @param labelName
	 *            the labelName to set
	 */
	public void setLabelName(String labelName) {
		label.setText(labelName);
	}

	public void setLabelColor(Color color) {
		label.setForeground(color);

	}
}
